unit Ai_simplestrategy;
{
  AI using stratgety
}
{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, basicIO_field, basicio_resources, basicio_city, basicio_player,
  basicio_street, basicio_trade, basicAI, basicIO_const, SystemManager, fgl;

type

  { TAI_SimpleStrategy }

  TAI_SimpleStrategy = class (TBasicAI)
    private
      FPhase : integer;
      FWoodValue : integer;
      FDirtValue : integer;
      FSheepsValue : integer;
      FWheatValue : integer;
      FOreValue : integer;
    public
      constructor create; override;
      destructor destroy; override;
    protected
      procedure CheckChangePhase;
      function ReturnCity: TCityPosition; Override;
      function ReturnStreet: TStreetPosition; Override;
      function ReturnAcceptTrade(AOffer: TTradeOffer): boolean; Override;
      function ReturnThiefField: TFieldPosition; Override;
      function ReturnThiefCity: TCityPosition; Override;
      function ReturnThrowRes(AAmount: integer): TResources; Override;
      function WantToTrade : boolean; Override;
      function WantTobuild(var ABuildOrder: TBuildOrder): boolean; override;
      function CityPosWanted: TCityPosition;
      function ReturnTradeOffer: TTradeOffer; override;
      function ReturnExtendCity: TCityPosition; override;
      function ReadyToAct: boolean; override;
      function DiceValue(Adice: integer): integer;
  end;
  
  TCityPosList = specialize TFPGList<TCityPosition>;
  
implementation

{ TAI_SimpleStrategy }

function TAI_SimpleStrategy.ReadyToAct: boolean;
begin
  result := true;
end;

function TAI_SimpleStrategy.DiceValue(Adice: integer): integer;
begin
  case Adice of
   2,12:
     begin
       result:= 1;
       exit;
     end;
   3,11:
     begin
       result := 2;
       exit
     end;
   4,10:
     begin
       result := 2;
       exit
     end;
   5,9:
     begin
       result := 3;
       exit
     end;
   6,8:
     begin
       result := 5;
       exit
     end;
  end;
end;

constructor TAI_SimpleStrategy.create;
begin
  inherited Create;
  FPhase := 1;
  FWoodValue := 5;
  FDirtValue := 5;
  FSheepsValue := 3;
  FWheatValue := 3;
  FOreValue := 1;
end;

destructor TAI_SimpleStrategy.destroy;
begin
  inherited Destroy;
end;
function TAI_SimpleStrategy.ReturnCity: TCityPosition;
var
  i: integer;
  j: integer;
  k: integer;
  ACityList : TCityPosList; //List of Cityposition planed to built at
  AFieldValue : Integer; // Value of the Field we wanna reach
  CheckedField : TField; // at the moment checked Field
  ACityPos : TCityPosition;
  ACityValue : integer;
  ACityCheckedValue : integer;
begin
  j:= 0;
  for i:= 0 to GlobalSystemManager.IO.data.map.CityCount - 1 do
  begin
    if not (GlobalSystemManager.IO.data.map.CityByID[i].owner = Nil) and ( GlobalSystemManager.IO.data.map.CityByID[i].owner = GlobalSystemManager.IO.Data.Player[AIPlayerID]) then
    begin
      j:= j + 1;
    end;
  end;
  if j < 2 then begin
    result := CityPosWanted;
    exit;
  end;
  AFieldValue := 0;
  ACityList := TCityPosList.Create;
  for i:=0 to 18 do
  begin
    CheckedField := GlobalSystemManager.IO.data.map.FieldsByPos[basicIO_const.FieldCityMap[i].FieldX, basicIO_const.FieldCityMap[i].FieldY];
    case CheckedField.kind of
     RK_Wood:
       begin
         if (DiceValue(CheckedField.dice) + FWoodValue) >= AFieldValue then
         begin
           for j:= 0 to 5 do
           begin
             if (IsValidCityPos(basicIO_const.FieldCityMap[i].cities[j])) then
             begin
               AFieldValue := DiceValue(CheckedField.dice) + FWoodValue;
               ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
             end;
           end;
         end;
       end;
     RK_Dirt:
     begin
       if (DiceValue(CheckedField.dice) + FDirtValue) >= AFieldValue then
       begin
         for j:= 0 to 5 do
         begin
           if (IsValidCityPos(basicIO_const.FieldCityMap[i].cities[j])) then
           begin
             AFieldValue := DiceValue(CheckedField.dice) + FDirtValue;
             ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
           end;
         end;
       end;
     end;
     RK_Sheeps:
       begin
         if (DiceValue(CheckedField.dice) + FSheepsValue) >= AFieldValue then
         begin
           for j:= 0 to 5 do
           begin
             if (IsValidCityPos(basicIO_const.FieldCityMap[i].cities[j])) then
             begin
               AFieldValue := DiceValue(CheckedField.dice) + FSheepsValue;
               ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
             end;
           end;
         end;
       end;
     RK_Wheat:
       begin
         if (DiceValue(CheckedField.dice) + FWheatValue) >= AFieldValue then
         begin
           for j:= 0 to 5 do
           begin
             if (IsValidCityPos(basicIO_const.FieldCityMap[i].cities[j])) then
             begin
               AFieldValue := DiceValue(CheckedField.dice) + FWheatValue;
               ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
             end;
           end;
         end;
       end;
     RK_Ore:
       begin
         if (DiceValue(CheckedField.dice) + FOreValue) >= AFieldValue then
         begin
           for j:= 0 to 5 do
           begin
             if (IsValidCityPos(basicIO_const.FieldCityMap[i].cities[j])) then
             begin
               AFieldValue := DiceValue(CheckedField.dice) + FOreValue;
               ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
             end;
           end;
         end;
       end;
     PK_None:
      begin
         if ( 0) >= AFieldValue then
         begin
           for j:= 0 to 5 do
           begin
             if (IsValidCityPos(basicIO_const.FieldCityMap[i].cities[j])) then
             begin
               AFieldValue := 0;
               ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
             end;
           end;
         end;
      end;
    end;
  end;
  ACityValue := 0;
  for i := 0 to ACityList.Count-1 do
  begin
    ACityCheckedValue := 0;
    for j := 0 to 18 do
    begin
      for k := 0 to 5 do
      begin
        if basicIO_const.FieldCityMap[j].cities[k] = ACityList.items[i] then
        begin
          CheckedField := GlobalSystemManager.IO.data.map.FieldsByPos[basicIO_const.FieldCityMap[i].FieldX, basicIO_const.FieldCityMap[i].FieldY];
          case  CheckedField.kind of
           RK_Wood:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FWoodValue;
             end;
           RK_Dirt:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FDirtValue;
             end;
           RK_Sheeps:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FSheepsValue;
             end;
           RK_Wheat:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FWheatValue;
             end;
           RK_Ore:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FOreValue;
             end;
           PK_None:
             begin
               ACityCheckedValue := ACityCheckedValue + 0;
             end;
          end;
          if  ACityCheckedValue > ACityValue then
          begin
            ACityPos := ACityList.items[i];
          end;
        end;
      end;
    end;
  end;
  result := ACityPos;
  ACityList.Free;
end;

function TAI_SimpleStrategy.ReturnStreet: TStreetPosition;
{var
  ASPointList : TCityPosList;
  AFPointList : TCityPosList;
  i: integer;
  j: integer;
  AStreetPosition : TStreetPosition;
  BStreetPosition : TStreetPosition; }   // code has some problems
begin
    result := StreetPosArray[random(high(StreetPosArray))];
 { ASPointList := TCityPosList.create;
  AFPointList := TCityPosList.create;
  for i:= 0 to GlobalSystemManager.IO.data.map.CityCount -1 do
  begin
    if (GlobalSystemManager.IO.data.map.CityByID[i].owner = GlobalSystemManager.IO.data.Player[AIPlayerID]) and not (GlobalSystemManager.IO.data.map.CityByID[i] = Nil) then
    begin
      ASPointList.Add(GlobalSystemManager.IO.data.map.CityByID[i].Position);
    end;
  end;
  for i:= 0 to GlobalSystemManager.IO.data.map.StreetCount -1 do
  begin
   if (GlobalSystemManager.IO.data.map.StreetByID[i].owner = GlobalSystemManager.IO.data.Player[AIPlayerID]) and not (GlobalSystemManager.IO.data.map.StreetByID[i] = Nil) then
    begin
      for j := 0 to ASPointList.Count-1 do
      begin
        if GlobalSystemManager.IO.data.map.StreetByID[i].position[0] = ASPointList.Items[j] then
        begin
          ASPointList.Add(GlobalSystemManager.IO.data.map.StreetByID[i].position[1]);
        end else
        if GlobalSystemManager.IO.data.map.StreetByID[i].position[1] = ASPointList.Items[j] then
        begin
          ASPointList.Add(GlobalSystemManager.IO.data.map.StreetByID[i].position[0]);
        end;
      end;
    end;
  end;
  for i:= 0 to 71 do
  begin
    for j := 0 to ASPointList.Count-1 do
    begin
      if basicIO_const.StreetPosArray[i][0] = ASPointList.Items[j] then
      begin
        AStreetPosition[0] := ASPointList.Items[j];
        AStreetPosition[1] := basicIO_const.StreetPosArray[i][1];
        if IsValidStreetPos(AStreetPosition)then
        begin
          AFPointList.Add(basicIO_const.StreetPosArray[i][1]);
        end;
      end else
      if basicIO_const.StreetPosArray[i][1] = ASPointList.Items[j] then
      begin
        AStreetPosition[0] := ASPointList.Items[j];
        AStreetPosition[1] := basicIO_const.StreetPosArray[i][0];
        if IsValidStreetPos(AStreetPosition)then
        begin
          AFPointList.Add(basicIO_const.StreetPosArray[i][1]);
        end;
      end;
    end;
  end;
  case FPhase of
   1,2:
   begin
    for i :=0 to ASPointList.Count-1 do
    begin
      for j :=0 to AFPointList.Count-1 do
      begin
        AStreetPosition[0] := ASPointList.Items[i];
        AStreetPosition[1] := AFPointList.Items[j];
        if IsValidStreetPos(AStreetPosition) then
        begin
          if AFPointList.Items[j] = CityPosWanted then
          begin
            result:= AStreetPosition;
            exit;
          end else
          begin
            BStreetPosition :=AStreetPosition;
          end;
        end;
        AStreetPosition[1] := ASPointList.Items[i];
        AStreetPosition[0] := AFPointList.Items[j];
        if IsValidStreetPos(AStreetPosition) then
        begin
          if AFPointList.Items[j] = CityPosWanted then
          begin
            result:= AStreetPosition;
            exit;
          end else
          BStreetPosition :=AStreetPosition;
        end;
      end;
    end;
    result:= BStreetPosition;
  end;
  3,4:
  begin
  for i :=0 to ASPointList.Count-1 do
    begin
      for j :=0 to AFPointList.Count-1 do
      begin
        AStreetPosition[0] := ASPointList.Items[i];
        AStreetPosition[1] := AFPointList.Items[j];
        if IsValidStreetPos(AStreetPosition) then
        begin
          result:= AStreetPosition;
          ASPointList.Free;
          AFPointList.Free;
          exit;
        end;
        AStreetPosition[1] := ASPointList.Items[i];
        AStreetPosition[0] := AFPointList.Items[j];
        if IsValidStreetPos(AStreetPosition) then
        begin
          result:= AStreetPosition;
          ASPointList.Free;
          AFPointList.Free;
          exit;
        end;
      end;
    end;
  end;
 end; }
end;

function TAI_SimpleStrategy.ReturnAcceptTrade(AOffer: TTradeOffer): boolean;
begin
  if (AOffer.WeGet.wood+AOffer.WeGet.wheat+AOffer.WeGet.dirt+AOffer.WeGet.ore+AOffer.WeGet.sheeps)
     > (AOffer.TheyGet.wood+AOffer.TheyGet.wheat+AOffer.TheyGet.dirt+AOffer.TheyGet.ore+AOffer.TheyGet.sheeps) then
  begin
    result := true;
  end else
  begin
    result := false;
  end;
end;

function TAI_SimpleStrategy.ReturnThiefField: TFieldPosition;
var
  i: integer;
  j: integer;
  k: integer;
  AFieldValue: integer;
  AField: TField;
  AFieldList: TFieldList;
begin
 AFieldList := TFieldList.create(false);
 for i:= 0 to 18 do
  begin
    for j:= 0 to 5 do
  begin
    if not (GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[i].Cities[j]].owner = GlobalSystemManager.IO.data.Player[AIPlayerID]) then
    begin
      AFieldList.Add(GlobalSystemManager.IO.data.map.FieldsByPos[basicIO_const.FieldCityMap[i].FieldX,basicIO_const.FieldCityMap[i].FieldY]);
    end;
  end;
  end;
 AField := AFieldList.items[0];
 AFieldValue := 0;
 for k:= 0 to AFieldList.Count-1 do
 begin
   case AFieldList.items[k].kind of
     RK_Wood:
       begin
         if (AFieldList.items[k].dice + FWoodValue) > AFieldValue then
         begin
           AField := AFieldList.items[k];
           AFieldValue := AFieldList.items[k].dice + FWoodValue;
         end;
       end;
     RK_Dirt:
     begin
         if (AFieldList.items[k].dice + FDirtValue) > AFieldValue then
         begin
           AField := AFieldList.items[k];
           AFieldValue := AFieldList.items[k].dice + FDirtValue;
         end;
       end;
     RK_Sheeps:
       begin
         if (AFieldList.items[k].dice + FSheepsValue) > AFieldValue then
         begin
           AField := AFieldList.items[k];
           AFieldValue := AFieldList.items[k].dice + FSheepsValue;
         end;
       end;
     RK_Wheat:
       begin
         if (AFieldList.items[k].dice + FWheatValue) > AFieldValue then
         begin
           AField := AFieldList.items[k];
           AFieldValue := AFieldList.items[k].dice + FWheatValue;
         end;
       end ;
     RK_Ore:
       begin
         if (AFieldList.items[k].dice + FOreValue) > AFieldValue then
         begin
           AField := AFieldList.items[k];
           AFieldValue := AFieldList.items[k].dice + FOreValue;
         end;
       end ;
     PK_None:
       begin
         if (AFieldList.items[k].dice + 0) > AFieldValue then
         begin
           AField := AFieldList.items[k];
           AFieldValue :=  0;
         end;
       end;
   end;
 end;
 AFieldList.Free;
 result := AField.position;
end;

function TAI_SimpleStrategy.ReturnThiefCity: TCityPosition;
{handles which city is chosen for robbing ressources}
var
  a: integer;
  i: integer;
  j: integer;
  stplayer: TPlayer;  // first player we would chose, if we could
  sndplayer: TPlayer; // second player we would chose, if we could
begin
  stplayer:= TPlayer.Create(PC_Unknown);   // placeholder with nothing created, so we could compare stplayer / sndplayer to all other players
  sndplayer:= TPlayer.Create(PC_Unknown);
  for a:= 1 to GlobalSystemManager.IO.data.PlayerCount do
  begin
    if not a = AIPlayerID then
    begin   // choice by comparing players Winpoints
      if GlobalSystemManager.IO.data.Player[a].PlayerResources.Winpoints >=  stplayer.PlayerResources.Winpoints then
      begin
        sndplayer := stplayer;
        stplayer := GlobalSystemManager.IO.data.Player[a];
      end else
      if GlobalSystemManager.IO.data.Player[a].PlayerResources.Winpoints >=  sndplayer.PlayerResources.Winpoints then
      begin
        sndplayer := GlobalSystemManager.IO.data.Player[a];
      end;
    end;
  end;
  for i:= 0 to 18 do
  begin
    if (GlobalSystemManager.IO.data.map.ThiefPositionAsPoint.x = basicIO_const.FieldCityMap[i].FieldX) and (GlobalSystemManager.IO.data.map.ThiefPositionAsPoint.y = basicIO_const.FieldCityMap[i].FieldY) then
    begin
      for j := 0 to 5 do
      begin
        if GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[i].Cities[j]].owner= stplayer then
        begin
          result:= basicIO_const.FieldCityMap[i].cities[j];
          exit;
        end;
      end;
      for j := 0 to 5 do
      begin
        if GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[i].Cities[j]].owner = sndplayer then
        begin
          result:= basicIO_const.FieldCityMap[i].cities[j];
          exit;
        end;
      end;
      for j := 0 to 18 do
      begin
        if (GlobalSystemManager.IO.data.map.ThiefPositionAsPoint.x = basicIO_const.FieldCityMap[j].FieldX)
            and (GlobalSystemManager.IO.data.map.ThiefPositionAsPoint.y = basicIO_const.FieldCityMap[j].FieldY) then
        begin
          for a:= 0 to 5 do
          begin
            if not(GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[j].Cities[a]].owner =  GlobalSystemManager.IO.data.Player[AIPlayerID])
               and not (GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[j].Cities[a]] = Nil) then
            begin
              result := basicIO_const.FieldCityMap[j].cities[a];
              exit;
            end;
          end;
        end;
      end;
    end;
  end;
end;

function TAI_SimpleStrategy.ReturnThrowRes(AAmount: integer): TResources;
var
  tRes : TResources;
  i: integer;
begin
  tRes := Resources(0,0,0,0,0);
  for i := 1 to AAmount do
  begin
    case FPhase of
    1:
      begin
        if HaveEnoughtRes(Resources(0,0,0,0,1)) then
        begin
           tRes := SumResources(tRes,Resources(0,0,0,0,1));
        end else
        begin
          if (HaveEnoughtRes(Resources(0,0,0,1,0)) or HaveEnoughtRes(Resources(0,0,1,0,0)) ) then
          begin
            if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.sheeps < GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wheat then
            begin
               tRes := SumResources(tRes,Resources(0,0,0,1,0));
            end else
            begin
               tRes := SumResources(tRes,Resources(0,0,1,0,0));
            end;
          end else
          begin
            if (HaveEnoughtRes(Resources(0,1,0,0,0)) or HaveEnoughtRes(Resources(1,0,0,0,0))) then
            begin
             if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood < GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt then
             begin
              tRes := SumResources(tRes,Resources(0,1,0,0,0));
             end else
             begin
               tRes := SumResources(tRes,Resources(1,0,0,0,0));
             end;
            end;
          end;
        end;
      end;
    2,3,4:
      begin
        if (self.HaveEnoughtRes(Resources(0,1,0,0,0)) or self.HaveEnoughtRes(Resources(1,0,0,0,0))) then
        begin
          if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood < GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt then
          begin
           tRes := SumResources(tRes,Resources(0,1,0,0,0));
          end else
          begin
            tRes := SumResources(tRes,Resources(1,0,0,0,0));
          end;
        end else
        begin
          if (self.HaveEnoughtRes(Resources(0,0,1,0,0))) then
          begin
            tRes := SumResources(tRes,Resources(0,0,1,0,0));
          end else
          begin
            if (self.HaveEnoughtRes(Resources(0,0,0,1,0)))then
            begin
              tRes := SumResources(tRes,Resources(0,0,0,1,0));
            end else
            begin
              if (self.HaveEnoughtRes(Resources(0,0,0,0,1)))then
              begin
                tRes := SumResources(tRes,Resources(0,0,0,0,1));
              end;
            end;
          end;
        end;
      end;
    end;
  end;
  result := tRes;
end;

function TAI_SimpleStrategy.WantToTrade: boolean;
begin
  case FPhase of
    1,2:  // we only want to trade if we have ore
      begin
        if (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.ore > 0) then
        begin
          result := true;
        end;
      end;
    3:  // we only want to trade if we have wood or dirt or sheeps
      begin
        if (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood > 0) or
           (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt > 0) or
           (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.sheeps > 0) then
        begin
          result := true
        end;
      end;
    4: // we only want to trade if we have wood or dirt
      begin
        if (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood > 0) or
           (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt > 0) then
        begin
          result := true
        end;
      end;
  end;
end;

function TAI_SimpleStrategy.WantTobuild(var ABuildOrder: TBuildOrder): boolean; // handles if AI wants to build
var
  finish: boolean;
  Aresult: boolean;
begin
  inherited;
  finish:= true;
  while finish do
  begin
    case FPhase of
      1:
      begin
        Aresult:= false;
        while finish do
        begin
          if CanBuildCity then
          begin
            FPhase := 2;
            FWoodValue := 0;
            FDirtValue := 0;
            FSheepsValue := 2;
            FWheatValue := 4;
            FOreValue := 5;
            ABuildOrder.Cities:= ABuildOrder.Cities +1;
            Aresult:= true;
            break;
          end else
          if CanBuildStreet then
          begin
            Aresult := true;
            ABuildOrder.Streets:= ABuildOrder.Streets +1;
            break;
          end else
          begin
            finish:= false;
          end;
        end;
      end;
      2:
      begin
        Aresult:= false;
        if CanBuildCity then
        begin
         FPhase := 3;
         ABuildOrder.Cities:= ABuildOrder.Cities +1;
         Aresult:= true;
         break;
        end else
        if CanBuildStreet then
        begin
          Aresult := true;
          ABuildOrder.Streets:= ABuildOrder.Streets +1;
          break;
        end else
        begin
          finish:= false;
        end;
      end;
      3:
      begin
        Aresult:= false;
        if CanExtendCity then
        begin
          ABuildOrder.ExtendCities:= ABuildOrder.ExtendCities +1;
          CheckChangePhase;
          Aresult:= true;
          break;
        end else
        begin
          if CanBuildStreet then
          begin
            Aresult := true;
            ABuildOrder.Streets:= ABuildOrder.Streets +1;
            break;
          end else
          begin
            finish:= false;
          end;
        end;
      end;
      4:
      begin
        if CanbuildInvention then
        begin
          ABuildOrder.Streets:= ABuildOrder.Streets +1;
          Aresult := true;
          break;
        end;
        if CanBuildStreet then
        begin
          Aresult := true;
          ABuildOrder.Streets:= ABuildOrder.Streets +1;
          break;
        end else
        begin
          finish:= false;
        end;
      end;
    end;
  end;
  result := Aresult;
end;
function TAI_SimpleStrategy.CityPosWanted: TCityPosition;
var
  i: integer;
  j: integer;
  k: integer;
  l: integer;
  ACityList : TCityPosList; //List of Cityposition planed to built at
  AFieldValue : Integer; // Value of the Field we wanna reach
  CheckedField : TField; // at the moment checked Field
  ACityPos : TCityPosition;
  ACityValue : integer;
  ACityCheckedValue : integer;
begin
  AFieldValue := 0;
  ACityList := TCityPosList.Create;
  for i:=0 to 18 do
  begin
    CheckedField := GlobalSystemManager.IO.data.map.FieldsByPos[basicIO_const.FieldCityMap[i].FieldX, basicIO_const.FieldCityMap[i].FieldY];
    case CheckedField.kind of
      RK_Wood:
      begin
        for j:= 0 to 5 do
        begin
          if GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[i].cities[j]] = Nil then
          begin
            for l:= 0 to 71 do
            begin
              if basicIO_const.StreetPosArray[l][0] = basicIO_const.FieldCityMap[i].cities[j] then
              begin
                if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][1]] = Nil then
                begin
                  AFieldValue := DiceValue(CheckedField.dice) + FWoodValue;
                  ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                end;
              end else
              if basicIO_const.StreetPosArray[l][1] = basicIO_const.FieldCityMap[i].cities[j] then
              begin
                if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][0]] = Nil then
                begin
                  AFieldValue := DiceValue(CheckedField.dice) + FWoodValue;
                  ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                end;
              end;
            end;
          end;
        end;
      end;
      RK_Dirt:
      begin
        if (DiceValue(CheckedField.dice) + FDirtValue) >= AFieldValue then
        begin
          for j:= 0 to 5 do
          begin
            if (GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[i].cities[j]]= Nil) then
            begin
              for l:= 0 to 71 do
              begin
                if basicIO_const.StreetPosArray[l][0] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][1]] = Nil then
                  begin
                    AFieldValue := DiceValue(CheckedField.dice) + FDirtValue;
                    ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end else
                if basicIO_const.StreetPosArray[l][1] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][0]] = Nil then
                  begin
                    AFieldValue := DiceValue(CheckedField.dice) + FDirtValue;
                    ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end;
              end;
            end;
          end;
        end;
      end;
      RK_Sheeps:
      begin
        if (DiceValue(CheckedField.dice) + FSheepsValue) >= AFieldValue then
        begin
          for j:= 0 to 5 do
          begin
            if (GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[i].cities[j]] = Nil) then
            begin
              for l:= 0 to 71 do
              begin
                if basicIO_const.StreetPosArray[l][0] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][1]] = Nil then
                  begin
                    AFieldValue := DiceValue(CheckedField.dice) + FSheepsValue;
                    ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end else
                if basicIO_const.StreetPosArray[l][1] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][0]] = Nil then
                  begin
                    AFieldValue := DiceValue(CheckedField.dice) + FSheepsValue;
                    ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end;
              end;
            end;
          end;
        end;
      end;
      RK_Wheat:
      begin
        if (DiceValue(CheckedField.dice) + FWheatValue) >= AFieldValue then
        begin
          for j:= 0 to 5 do
          begin
            if (GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[i].cities[j]] = Nil) then
            begin
              for l:= 0 to 71 do
              begin
                if basicIO_const.StreetPosArray[l][0] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][1]] = Nil then
                  begin
                    AFieldValue := DiceValue(CheckedField.dice) + FWheatValue;
                    ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end else
                if basicIO_const.StreetPosArray[l][1] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][0]] = Nil then
                  begin
                     AFieldValue := DiceValue(CheckedField.dice) + FWheatValue;
                     ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end;
              end;
            end;
          end;
        end;
      end;
      RK_Ore:
      begin
        if (DiceValue(CheckedField.dice) + FOreValue) >= AFieldValue then
        begin
          for j:= 0 to 5 do
          begin
            if (GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[i].cities[j]] = Nil) then
            begin
              for l:= 0 to 71 do
              begin
                if basicIO_const.StreetPosArray[l][0] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][1]] = Nil then
                  begin
                    AFieldValue := DiceValue(CheckedField.dice) + FOreValue;
                    ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end else
                if basicIO_const.StreetPosArray[l][1] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][0]] = Nil then
                  begin
                    AFieldValue := DiceValue(CheckedField.dice) + FOreValue;
                    ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end;
              end;
            end;
          end;
        end;
      end;
      PK_None:
      begin
        if 0 >= AFieldValue then
        begin
          for j:= 0 to 5 do
          begin
            if (GlobalSystemManager.IO.data.map.CityByPos[basicIO_const.FieldCityMap[i].cities[j]] = Nil) then
            begin
              for l:= 0 to 71 do
              begin
                if basicIO_const.StreetPosArray[l][0] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][1]] = Nil then
                  begin
                    AFieldValue := 0;
                    ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end else
                if basicIO_const.StreetPosArray[l][1] = basicIO_const.FieldCityMap[i].cities[j] then
                begin
                  if GlobalSystemManager.IO.data.Map.CityByPos[basicIO_const.StreetPosArray[l][0]] = Nil then
                  begin
                    AFieldValue := 0;
                    ACityList.Add(basicIO_const.FieldCityMap[i].cities[j]);
                  end;
                end;
              end;
            end;
          end;
        end;
      end;
    end;
  end;
  ACityValue := 0;
  for i := 0 to ACityList.Count-1 do
  begin
    ACityCheckedValue := 0;
    for j := 0 to 18 do
    begin
      for k := 0 to 5 do
      begin
        if basicIO_const.FieldCityMap[j].cities[k] = ACityList.items[i] then
        begin
          CheckedField := GlobalSystemManager.IO.data.map.FieldsByPos[basicIO_const.FieldCityMap[j].FieldX, basicIO_const.FieldCityMap[j].FieldY];
          case  CheckedField.kind of
           RK_Wood:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FWoodValue;
             end;
           RK_Dirt:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FDirtValue;
             end;
           RK_Sheeps:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FSheepsValue;
             end;
           RK_Wheat:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FWheatValue;
             end;
           RK_Ore:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FOreValue;
             end;
           PK_None:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice);
             end;
          end;
          if  ACityCheckedValue > ACityValue then
          begin
            ACityPos := ACityList.items[i];
          end;
        end;
      end;
    end;
  end;
  result := ACityPos;
  ACityList.Free;
end;

function TAI_SimpleStrategy.ReturnTradeOffer: TTradeOffer;
var
  WeGet: TResources;
  TheyGet: TResources;
begin
  case FPhase of
   1,2:
   begin
     if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood > GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt then
     begin
       if (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.ore < 3) then
       begin
         WeGet.wood:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.ore;
         WeGet.dirt:= 0;
         WeGet.wheat:= 0;
         WeGet.sheeps:= 0;
         WeGet.ore:= 0;
         TheyGet.wood:= 0;
         TheyGet.dirt:= 0;
         TheyGet.wheat:= 0;
         TheyGet.sheeps:= 0;
         TheyGet.ore:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.ore;
       end else
       begin
         WeGet.wood:= 1;
         WeGet.dirt:= 0;
         WeGet.wheat:= 0;
         WeGet.sheeps:= 0;
         WeGet.ore:= 0;
         TheyGet.wood:= 0;
         TheyGet.dirt:= 0;
         TheyGet.wheat:= 0;
         TheyGet.sheeps:= 0;
         TheyGet.ore:= 3;
       end;
     end;
       if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood <= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt then
     begin
       if (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.ore < 3) then
       begin
         WeGet.wood:= 0;
         WeGet.dirt:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.ore;
         WeGet.wheat:= 0;
         WeGet.sheeps:= 0;
         WeGet.ore:= 0;
         TheyGet.wood:= 0;
         TheyGet.dirt:= 0;
         TheyGet.wheat:= 0;
         TheyGet.sheeps:= 0;
         TheyGet.ore:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.ore;
       end else
       begin
         WeGet.wood:= 0;
         WeGet.dirt:= 1;
         WeGet.wheat:= 0;
         WeGet.sheeps:= 0;
         WeGet.ore:= 0;
         TheyGet.wood:= 0;
         TheyGet.dirt:= 0;
         TheyGet.wheat:= 0;
         TheyGet.sheeps:= 0;
         TheyGet.ore:= 3;
       end;
     end;
     result.WeGet := WeGet;
     result.TheyGet := TheyGet;
   end;
   3,4:
   begin
     if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wheat < GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.ore then
     begin
       if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood > GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt then
       begin
         if (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood < 3) then
         begin
           WeGet.wood:= 0;
           WeGet.dirt:= 0;
           WeGet.wheat:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood;
           WeGet.sheeps:= 0;
           WeGet.ore:= 0;
           TheyGet.wood:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood;
           TheyGet.dirt:= 0;
           TheyGet.wheat:= 0;
           TheyGet.sheeps:= 0;
           TheyGet.ore:= 0;
         end else
         begin
           WeGet.wood:= 0;
           WeGet.dirt:= 0;
           WeGet.wheat:= 1;
           WeGet.sheeps:= 0;
           WeGet.ore:= 0;
           TheyGet.wood:= 3;
           TheyGet.dirt:= 0;
           TheyGet.wheat:= 0;
           TheyGet.sheeps:= 0;
           TheyGet.ore:= 0;
         end;
       end else
       if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood >= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt then
       begin
         if (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt < 3) then
         begin
           WeGet.wood:= 0;
           WeGet.dirt:= 0;
           WeGet.wheat:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt;
           WeGet.sheeps:= 0;
           WeGet.ore:= 0;
           TheyGet.wood:= 0;
           TheyGet.dirt:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt;
           TheyGet.wheat:= 0;
           TheyGet.sheeps:= 0;
           TheyGet.ore:= 0;
         end else
         begin
           WeGet.wood:= 0;
           WeGet.dirt:= 0;
           WeGet.wheat:= 1;
           WeGet.sheeps:= 0;
           WeGet.ore:= 0;
           TheyGet.wood:= 0;
           TheyGet.dirt:= 3;
           TheyGet.wheat:= 0;
           TheyGet.sheeps:= 0;
           TheyGet.ore:= 0;
         end;
       end;
     end else
     begin
     if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wheat <= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.ore then
     begin
       if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood > GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt then
       begin
         if (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood < 3) then
         begin
           WeGet.wood:= 0;
           WeGet.dirt:= 0;
           WeGet.wheat:= 0;
           WeGet.sheeps:= 0;
           WeGet.ore:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood;
           TheyGet.wood:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood;
           TheyGet.dirt:= 0;
           TheyGet.wheat:= 0;
           TheyGet.sheeps:= 0;
           TheyGet.ore:= 0;
         end else
         begin
           WeGet.wood:= 0;
           WeGet.dirt:= 0;
           WeGet.wheat:= 0;
           WeGet.sheeps:= 0;
           WeGet.ore:= 1;
           TheyGet.wood:= 3;
           TheyGet.dirt:= 0;
           TheyGet.wheat:= 0;
           TheyGet.sheeps:= 0;
           TheyGet.ore:= 0;
         end;
       end else
       begin
         if GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.wood >= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt then
         begin
           if (GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt < 3) then
           begin
           WeGet.wood:= 0;
           WeGet.dirt:= 0;
           WeGet.wheat:= 0;
           WeGet.sheeps:= 0;
           WeGet.ore:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt;
           TheyGet.wood:= 0;
           TheyGet.dirt:= GlobalSystemManager.IO.Data.Player[AIPlayerID].Resources.dirt;
           TheyGet.wheat:= 0;
           TheyGet.sheeps:= 0;
           TheyGet.ore:= 0;
           end else
           begin
           WeGet.wood:= 0;
           WeGet.dirt:= 0;
           WeGet.wheat:= 0;
           WeGet.sheeps:= 0;
           WeGet.ore:= 1;
           TheyGet.wood:= 0;
           TheyGet.dirt:= 3;
           TheyGet.wheat:= 0;
           TheyGet.sheeps:= 0;
           TheyGet.ore:= 0;
           end;
         end;
       end;
     end;
     end;
     result.WeGet := WeGet;
     result.TheyGet := TheyGet;
   end;
  end;
end;

function TAI_SimpleStrategy.ReturnExtendCity: TCityPosition;
var
  i: integer;
  j: integer;
  k: integer;
  ACityPos : TCityPosition;
  ACityList: TCityPosList;
  ACityValue : integer;
  ACityCheckedValue : integer;
  CheckedField : TField;
begin
   ACityList:= TCityPosList.Create;
  for i:= 0 to GlobalSystemManager.IO.data.map.CityCount -1 do
  begin
    if (GlobalSystemManager.IO.data.map.CityByID[i].owner = GlobalSystemManager.IO.Data.Player[AIPlayerID])
       and not GlobalSystemManager.IO.data.map.CityByID[i].isExtended then
    begin
      ACityList.Add(GlobalSystemManager.IO.data.map.CityByID[i].position);
    end;
  end;
  ACityValue := 0;
  for i := 0 to ACityList.Count-1 do
  begin
    ACityCheckedValue := 0;
    for j := 0 to 18 do
    begin
      for k := 0 to 5 do
      begin
        if basicIO_const.FieldCityMap[j].cities[k] = ACityList.items[i] then
        begin
          CheckedField := GlobalSystemManager.IO.data.map.FieldsByPos[basicIO_const.FieldCityMap[i].FieldX, basicIO_const.FieldCityMap[i].FieldY];
          case  CheckedField.kind of
           RK_Wood:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FWoodValue;
             end;
           RK_Dirt:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FDirtValue;
             end;
           RK_Sheeps:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FSheepsValue;
             end;
           RK_Wheat:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FWheatValue;
             end;
           RK_Ore:
             begin
               ACityCheckedValue := ACityCheckedValue + DiceValue(CheckedField.dice) + FOreValue;
             end;
           PK_None:
             begin
               ACityCheckedValue := ACityCheckedValue + 0;
             end;
          end;
        end;
        if  ACityCheckedValue > ACityValue then
        begin
          ACityPos := ACityList.items[i];
        end;
      end;
    end;
  end;
  result := ACityPos
end;

procedure TAI_SimpleStrategy.CheckChangePhase;
var
  textendedCities : integer;
  i : integer;
begin
  textendedCities := 0;
  for i:=0 to GlobalSystemManager.IO.data.map.CityCount - 1 do
  begin
    if GlobalSystemManager.IO.data.map.CityByID[i].Owner = GlobalSystemManager.IO.Data.Player[AIPlayerID] then
    begin
      if GlobalSystemManager.IO.data.map.CityByID[i].isExtended then
      begin
        inc(textendedCities);
      end;
    end;
  end;
  if textendedCities = 4 then
  begin
    FPhase := 4;
  end;
end;

initialization
  GlobalSystemManager.RegisterAISystem(TAI_SimpleStrategy);
end.  
      

      

